/*
 * ksamp.c
 *
 * Programa principal: ksamp. Recolecta y muestra información provista por
 * el kernel de Linux, tomada del sistema de archivos virtual /proc
 *
 */

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef DEBUG
#	include <mcheck.h>
#endif

#include "kernel_info.h"
#include "ksamp_options.h"

#define PROCDIR "/proc"

/* Se definen más abajo las siguientes: */
static void show_help (const char *program_name);

/*
 * Punto de ingreso al programa
 */
int main (int argc, char **argv) {
	KernelInfo *info = NULL;
	Options *options = NULL;

#ifdef DEBUG
	mtrace ();
#endif
	
	/* Parseo de línea de comandos*/
	options = parse_options (argc, argv);
	if (!options_is_valid (options)) {
		fprintf (stderr, "%s", options_get_error (options)->data);
		show_help (argv[0]);
		options_destroy (options);
		return EXIT_FAILURE; /* Salir fallando */
	}
	
	/* Información básica */
	info = kernel_info_new (PROCDIR);
	kernel_info_print (info, stdout,
	     "\n"
	     "Reporte sobre $hostname$ al $date$\n"
	     "  Tipo de CPU:     $cpu_type$\n"
	     "  Modelo de CPU:   $cpu_model$\n"
	     "  Linux kernel:    $kernel_major$.$kernel_minor$.$kernel_svn$$kernel_tag$\n"
	     "  Uptime:          $uptime_f$\n"
	     "\n"
	);
	
	if (options_get_mode (options) >= MODE_STATISTICS) {
		kernel_info_print (info, stdout,
			"Estadísticas:\n"
			"  Uso de CPU:\n"
			"    usuario = $cputime_user$s\n"
			"    sistema = $cputime_system$s\n"
			"    idle    = $cputime_idle$s\n"
			"  # cambios de contexto:    $context_switches$\n"
			"  Sistema iniciado el:      $boot_date$\n"
			"  Procesos totales creados: $total_processes$\n"
			"\n"
		);
	}
	
	if (options_get_mode (options) >= MODE_LOOPED) {
		int remaining = options_get_duration (options);
		int interval = options_get_interval (options);
		kernel_info_print(info, stdout,
			"  Peticiones a disco:		$disk_requests$\n"
			"  Memoria (disponible/total):	$mem_available$/$mem_total$\n"
			"  Promedio de carga (1 min):	$load_average_1$\n"
			"\n"
			);
		do {			
			kernel_info_update (info);
			/* Demora... */
			if (remaining < interval) {
				sleep (remaining);
			} else {
				sleep (interval);
				kernel_info_print(info, stdout,
					"  Peticiones a disco:		$disk_requests$\n"
					"  Memoria (disponible/total):	$mem_available$/$mem_total$\n"
					"  Promedio de carga (1 min):	$load_average_1$\n"
					"\n"
				);
			}
			remaining -= interval;
		} while (remaining > 0);
	}
	kernel_info_destroy (info);
	options_destroy (options);
	/* Salir con éxito */
	return EXIT_SUCCESS;
}

/*
 * Muestra un mensaje de ayuda. `program_name' indica como invocar ksamp
 */
static void show_help (const char *program_name) {
	fprintf (stderr,
		"\n"
		"KSAMP - Monitor de información de kernel\n"
		"\n"
		"Modos de uso:\n"
		"	%s\n"
		"	%s -s\n"
		"	%s -l <intervalo> <duración>\n"
		"\n"
		"La invocación sin argumentos muestra información general del sistema.\n"
		"Con la opción -s se agrega a lo anterior estadísticas de CPU, y del SO.\n"
		"Con la opción -l se muestra lo anterior, y luego se vuelcan estadísticas\n"
		" adicionales de carga, disco, y memoria durante <duración> segundos,\n"
		" con actualizaciones cada <intervalo> segundos.\n\n",
		program_name, program_name, program_name);
}
